#include "socket_programmer.h"
#include <arpa/inet.h>
#include <cstring>
#include <iostream>
#include <sys/resource.h>
#include <sys/socket.h>
#include <unistd.h>

int advanced_client::bind_client_ip(const std::string client_ip, uint16_t port)
{
    int ret = 0;

    switch (this->get_addr_family()) {
    case AF_INET: {
        sockaddr_in *ipv4_addr = reinterpret_cast<sockaddr_in *>(this->client_addr);
        ipv4_addr->sin_family = AF_INET;
        inet_pton(AF_INET, client_ip.c_str(), &ipv4_addr->sin_addr);
        ipv4_addr->sin_port = htons(port);
        break;
    }
    case AF_INET6: {
        sockaddr_in6 *ipv6_addr = reinterpret_cast<sockaddr_in6 *>(this->client_addr);
        ipv6_addr->sin6_family = AF_INET6;
        inet_pton(AF_INET6, client_ip.c_str(), &ipv6_addr->sin6_addr);
        ipv6_addr->sin6_port = htons(port);
        break;
    }
    default:
        std::cout << "暂时不支持这个地址族: " << this->get_addr_family() << std::endl;
        return -1;
    }

    ret = bind(this->get_fd(), this->client_addr, this->get_addr_family() == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6));

    if (ret == -1) {
        std::cout << "Fail to bind ip: " << client_ip << " port: " << port << std::endl;
    }

    return ret;
}

int tcpsocket::connect_host(const std::string addr, int port)
{
    int ret = 0;

    switch (this->addr_family) {
    case AF_INET: {
        sockaddr_in *ipv4_addr = reinterpret_cast<sockaddr_in *>(this->server_addr);
        ipv4_addr->sin_family = AF_INET;
        inet_pton(AF_INET, addr.c_str(), &ipv4_addr->sin_addr.s_addr);
        ipv4_addr->sin_port = htons(port);
        break;
    }
    case AF_INET6: {
        sockaddr_in6 *ipv6_addr = reinterpret_cast<sockaddr_in6 *>(this->server_addr);
        ipv6_addr->sin6_family = AF_INET6;
        inet_pton(AF_INET6, addr.c_str(), ipv6_addr->sin6_addr.__in6_u.__u6_addr8);
        ipv6_addr->sin6_port = htons(port);
        break;
    }
    default:
        std::cout << "暂时不支持这个地址族: " << this->addr_family << std::endl;
        return -1;
    }

    ret = connect(this->fd, this->server_addr, this->addr_family == AF_INET6 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in));

    if (ret == -1) {
        perror("Fail to connect server");
        return ret;
    }
    std::cout << "Connect server successfully" << std::endl;

    return ret;
}

int main()
{
    struct rlimit rl;
    rl.rlim_cur = RLIM_INFINITY; // 设置当前限制为无限
    rl.rlim_max = RLIM_INFINITY; // 设置最大限制为无限
    setrlimit(RLIMIT_CORE, &rl); // 设置 Core Dump 文件大小限制

    int recv_msg_len = 0;
    char recv_msg_buf[1024] = {0};
    char send_msg_buf[1024] = {0};
    int send_times = 0;

    advanced_client client_socket(AF_INET6);

    if (client_socket.bind_client_ip("2222::1", 0) == -1) {
        return -1;
    }

    if (client_socket.connect_host(std::string("1111::1"), 6666) == -1) {
        return -1;
    }

    display_client_info(AF_INET6, client_socket.get_server_addr());

    while (true) {
        bzero(send_msg_buf, sizeof(send_msg_buf));
        bzero(recv_msg_buf, sizeof(recv_msg_buf));

        sprintf(send_msg_buf, "我是客户端，这是我第%d次发消息, 发完之后我要睡 %d 毫秒\n", send_times, send_times);
        write(client_socket.get_fd(), send_msg_buf, strlen(send_msg_buf) + 1);

        recv_msg_len = read(client_socket.get_fd(), recv_msg_buf, sizeof(recv_msg_buf));
        if (recv_msg_len > 0) {
            std::cout << "服务器发来了一条消息：" << recv_msg_buf << std::endl;
        } else if (recv_msg_len == 0) {
            std::cout << "服务器已经关闭了连接..." << std::endl;
            break;
        } else {
            perror("连接出现了一些错误...");
            break;
        }

        usleep(send_times * 1000);
        ++send_times;
    }

    return 0;
}